package com.gpb.common.mybatis;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.ibatis.executor.parameter.DefaultParameterHandler;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;

import com.gpb.common.mybatis.dialect.Dialect;
import com.gpb.common.page.Paginable;

/**
 * 物理分页设置
 * @author Poppy Kwoks
 * @dateTime Apr 20, 2014  1:51:25 PM
 */
public class PaginationInterceptor implements Interceptor {

	Dialect dialect;
	public Object plugin(Object target) {
		if(dialect!=null){
			if(target instanceof org.apache.ibatis.executor.statement.RoutingStatementHandler) {
				org.apache.ibatis.executor.statement.RoutingStatementHandler statementHandler=(org.apache.ibatis.executor.statement.RoutingStatementHandler)target;
				BoundSql boundSql = statementHandler.getBoundSql();
				MetaObject metaStatementHandler = MetaObject.forObject(statementHandler);
				RowBounds rowBounds = (RowBounds)metaStatementHandler.getValue("delegate.rowBounds");
				if(rowBounds == null || rowBounds == RowBounds.DEFAULT){
					return target;
				}
				Paginable paginable=(Paginable)rowBounds;
				//是否获取记录总数
				if(paginable.isGetTotalCount()){
					Configuration configuration = (Configuration)metaStatementHandler.getValue("delegate.configuration");
					try {
						MappedStatement mappedStatement=(MappedStatement)metaStatementHandler.getValue("delegate.mappedStatement");
						BoundSql countBoundSql = new BoundSql(configuration,dialect.getCountSql(boundSql.getSql()),boundSql.getParameterMappings(),boundSql.getParameterObject());  
						ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, boundSql.getParameterObject(), countBoundSql);  
					       //通过connection建立一个countSql对应的PreparedStatement对象。
					       PreparedStatement pstmt = null;
					       ResultSet rs = null;
					       try {
					           pstmt = configuration.getEnvironment().getDataSource().getConnection().prepareStatement(dialect.getCountSql(boundSql.getSql()));
					           //通过parameterHandler给PreparedStatement对象设置参数
					           parameterHandler.setParameters(pstmt);
					           //之后就是执行获取总记录数的Sql语句和获取结果了。
					           rs = pstmt.executeQuery();
					           if (rs.next()) {
					        	   paginable.setTotalCount(rs.getInt(1));
					           }
					       } catch (SQLException e) {
					           e.printStackTrace();
					       } finally {
					           try {
					              if (rs != null)
					                  rs.close();
					               if (pstmt != null)
					                  pstmt.close();
					           } catch (SQLException e) {
					              e.printStackTrace();
					           }
					       }
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				//设置分页
				metaStatementHandler.setValue("delegate.boundSql.sql", dialect.getLimitSql(boundSql.getSql(), paginable.getOffset(), paginable.getLimit()) );
				metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET );
				metaStatementHandler.setValue("delegate.rowBounds.limit",paginable.getLimit());
				

			}
		}
		return target;
	}

	public Dialect getDialect() {
		return dialect;
	}

	public void setDialect(Dialect dialect) {
		this.dialect = dialect;
	}


	public Object intercept(Invocation invocation) throws Throwable {
		// TODO Auto-generated method stub
		return null;
	}


	public void setProperties(Properties properties) {
		// TODO Auto-generated method stub
		
	}

}